<?php
namespace Entity;

class Map
{
    const ROWNUM        = 15;
    const COLNUM        = 15;
    
    const WON           = 1;
    const LOST          = 2;
    
    private $field      = array();
    private $id         = NULL;
    private $p1         = NULL;
    private $p2         = NULL;
    private $p1Fields   = NULL;
    private $p2Fields   = NULL;
    
    public function __construct($id, $p1, $p2)
    {
        if ( ! is_numeric($id))
            throw new \InvalidArgumentException('id');
        if ( ! $p1)
            throw new \InvalidArgumentException('p1');
        if ( ! $p2)
            throw new \InvalidArgumentException('p2');
        
        
        for ($i = 0; $i < self::ROWNUM; ++$i)
            for ($j = 0; $j < self::COLNUM; ++$j)
            {
                $this->field[$i][$j] = 0;
            }
        
        $this->id       = $id;
        $this->p1       = $p1;
        $this->p2       = $p2;
        $this->p1Fields = array();
        $this->p2Fields = array();
    }
    
    public function getId()
    {
        return $this->id;
    }
    
    public function getP1()
    {
        return $this->p1;
    }
    
    public function getP2()
    {
        return $this->p2;
    }
    
    public function getOtherPlayer($player_id)
    {
        if ((int)$player_id === (int)$this->p1) return $this->p2;
        return (int)$this->p1;
    }
    
    public function isPlayer1($player_id)
    {
        if ((int)$player_id === (int)$this->p1) return TRUE;
        return FALSE;
    }
    
    public function getP1Fields()
    {
        return $this->p1Fields;
    }
    
    public function getP2Fields()
    {
        return $this->p2Fields;
    }
    
    public function getField($x, $y)
    {
        if ($x < 0 || $x > self::ROWNUM ||
            $y < 0 || $y > self::COLNUM)
            throw new InvalidArgumentException('x || y');
        
        if ($x && $y)
            return $this->field[$x][$y];
        
        return $this->field;
    }
    
    public function issetField($x, $y)
    {
        if ($this->field[$x][$y] === 0) return FALSE;
        return TRUE;
    }
    
    public function setField($x, $y, $val)
    {
        if ($x < 0 || $x > self::ROWNUM ||
            $y < 0 || $y > self::COLNUM)
            throw new InvalidArgumentException('x || y');
        
        if ($val === 1)
            $this->p1Fields[] = array($x, $y);
        else if ($val === 2)
            $this->p2Fields[] = array($x, $y);
        
        $this->field[$x][$y] = $val;
    }
    
    public function calcFive(array $playerFields, $val, array &$won_spots)
    {
        foreach ($playerFields as $field)
        {
            //---------------------------------------------
            // vertical
            $count = 1;
            
            // vertical top
            for ($i = 1; $i <= 4; ++$i)
            {
                if ( ! isset($this->field[$field[0]][$field[1]-$i]) ||
                    $this->field[$field[0]][$field[1]-$i] !== $val)
                {
                    break;
                }
                ++$count;
            }
            
            // five in a row?
            if ($count === 5)
            {
                // exactly five in a row?
                if (( ! isset($this->field[$field[0]][$field[1]-$i-1]) ||
                    $this->field[$field[0]][$field[1]-$i-1] !== $val) &&
                    ( ! isset($this->field[$field[0]][$field[1]+1]) ||
                    $this->field[$field[0]][$field[1]+1] !== $val))
                {
                    // winner spots
                    $won_spots[] = 8;
                    $won_spots[] = array($field[0], $field[1]-$i+1);
                    $won_spots[] = array($field[0], $field[1]);
                    
                    return self::WON;
                }
                // more than five in a row
                return self::LOST;
            }
            
            // vertical bottom
            for ($j = 1; $j <= 4; ++$j)
            {
                if ( ! isset($this->field[$field[0]][$field[1]+$j]) ||
                    $this->field[$field[0]][$field[1]+$j] !== $val)
                {
                    break;
                }
                ++$count;
                
                // five in a row?
                if ($count === 5)
                {
                    // exactly five in a row?
                    if ( ! isset($this->field[$field[0]][$field[1]+$j+1]) ||
                        $this->field[$field[0]][$field[1]+$j+1] !== $val)
                    {
                        // winner spots
                        $won_spots[] = 8;
                        $won_spots[] = array($field[0], $field[1]-$i+1);
                        $won_spots[] = array($field[0], $field[1]+$j);
                        
                        return self::WON;
                    }
                    // more than five in a row
                    return self::LOST;
                }
            }

            //---------------------------------------------
            // horizontal
            $count = 1;

            // horizontal left
            for ($i = 1; $i <= 4; ++$i)
            {
                if ( ! isset($this->field[$field[0]-$i][$field[1]]) ||
                    $this->field[$field[0]-$i][$field[1]] !== $val)
                {
                    break;
                }
                ++$count;
            }

            // five in a row?
            if ($count === 5)
            {
                // exactly five in a row?
                if (( ! isset($this->field[$field[0]-$i-1][$field[1]]) ||
                    $this->field[$field[0]-$i-1][$field[1]] !== $val) &&
                    ( ! isset($this->field[$field[0]+1][$field[1]]) ||
                    $this->field[$field[0]+1][$field[1]] !== $val))
                {
                    // winner spots
                    $won_spots[] = 4;
                    $won_spots[] = array($field[0]-$i+1, $field[1]);
                    $won_spots[] = array($field[0], $field[1]);
                    
                    return self::WON;
                }
                // more than five in a row
                return self::LOST;
            }


            // horizontal right
            for ($j = 1; $j <= 4; ++$j)
            {
                if ( ! isset($this->field[$field[0]+$j][$field[1]]) ||
                    $this->field[$field[0]+$j][$field[1]] !== $val)
                {
                    break;
                }
                ++$count;

                // five in a row?
                if ($count === 5)
                {
                    // exactly five in a row?
                    if ( ! isset($this->field[$field[0]+$j+1][$field[1]]) ||
                        $this->field[$field[0]+$j+1][$field[1]] !== $val)
                    {
                        // winner spots
                        $won_spots[] = 4;
                        $won_spots[] = array($field[0]-$i+1, $field[1]);
                        $won_spots[] = array($field[0]+$j, $field[1]);
                        
                        return self::WON;
                    }
                    // more than five in a row
                    return self::LOST;
                }
            }

            //---------------------------------------------
            // left diagonal
            $count = 1;
            
            // left diagonal top
            for ($i = 1; $i <= 4; ++$i)
            {
                if ( ! isset($this->field[$field[0]-$i][$field[1]-$i]) ||
                    $this->field[$field[0]-$i][$field[1]-$i] !== $val)
                {
                    break;
                }
                ++$count;
            }
            
            // five in a row?
            if ($count === 5)
            {
                // exactly five in a row?
                if (( ! isset($this->field[$field[0]-$i-1][$field[1]-$i-1]) ||
                    $this->field[$field[0]-$i-1][$field[1]-$i-1] !== $val) &&
                    ( ! isset($this->field[$field[0]+1][$field[1]+1]) ||
                    $this->field[$field[0]+1][$field[1]+1] !== $val))
                {
                    // winner spots
                    $won_spots[] = 7;
                    $won_spots[] = array($field[0]-$i+1, $field[1]-$i+1);
                    $won_spots[] = array($field[0], $field[1]);
                    
                    return self::WON;
                }
                // more than five in a row
                return self::LOST;
            }
                
            
            // left diagonal bottom
            for ($j = 1; $j <= 4; ++$j)
            {
                if ( ! isset($this->field[$field[0]+$j][$field[1]+$j]) ||
                    $this->field[$field[0]+$j][$field[1]+$j] !== $val)
                {
                    break;
                }
                ++$count;
                
                // five in a row?
                if ($count === 5)
                {
                    // exactly five in a row?
                    if ( ! isset($this->field[$field[0]+$j+1][$field[1]+$j+1]) ||
                        $this->field[$field[0]+$j+1][$field[1]+$j+1] !== $val)
                    {
                        // winner spots
                        $won_spots[] = 7;
                        $won_spots[] = array($field[0]-$i+1, $field[1]-$i+1);
                        $won_spots[] = array($field[0]+$j, $field[1]+$j);
                        
                        return self::WON;
                    }
                    // more than five in a row
                    return self::LOST;
                }
            }
            
            //---------------------------------------------
            // right diagonal
            $count = 1;
            
            // right diagonal top
            for ($i = 1; $i <= 4; ++$i)
            {
                if ( ! isset($this->field[$field[0]+$i][$field[1]-$i]) ||
                    $this->field[$field[0]+$i][$field[1]-$i] !== $val)
                {
                    break;
                }
                ++$count;
            }
            
            // five in a row?
            if ($count === 5)
            {
                // exactly five in a row?
                if (( ! isset($this->field[$field[0]+$i+1][$field[1]-$i-1]) ||
                    $this->field[$field[0]+$i+1][$field[1]-$i-1] !== $val) &&
                    ( ! isset($this->field[$field[0]-1][$field[1]+1]) ||
                    $this->field[$field[0]-1][$field[1]+1] !== $val))
                {
                    // winner spots
                    $won_spots[] = 9;
                    $won_spots[] = array($field[0]+$i-1, $field[1]-$i+1);
                    $won_spots[] = array($field[0], $field[1]);
                    
                    return self::WON;
                }
                // more than five in a row
                return self::LOST;
            }
                
            
            // right diagonal bottom
            for ($j = 1; $j <= 4; ++$j)
            {
                if ( ! isset($this->field[$field[0]-$j][$field[1]+$j]) ||
                    $this->field[$field[0]-$j][$field[1]+$j] !== $val)
                {
                    break;
                }
                ++$count;
                
                // five in a row?
                if ($count === 5)
                {
                    // exactly five in a row?
                    if ( ! isset($this->field[$field[0]-$j-1][$field[1]+$j+1]) ||
                        $this->field[$field[0]-$j-1][$field[1]+$j+1] !== $val)
                    {
                        // winner spots
                        $won_spots[] = 9;
                        $won_spots[] = array($field[0]+$i-1, $field[1]-$i+1);
                        $won_spots[] = array($field[0]-$j, $field[1]+$j);
                        
                        return self::WON;
                    }
                    // more than five in a row
                    return self::LOST;
                }
            }
        }
    }
}

#eof
